
#include "StdAfx.h"
#include "MemoryManager.h"
#include "platform.h"
#include "MemReplay.h"
#include "CustomMemoryHeap.h"
#include "GeneralMemoryHeap.h"
#include "PageMappingHeap.h"
#include "LevelHeap.h"

#if defined(WIN32) && !defined(XENON)
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>
	#include <Psapi.h>
#endif


extern long g_TotalAllocatedMemory;

#ifdef MEMMAN_STATIC
CCryMemoryManager g_memoryManager;
#endif

//////////////////////////////////////////////////////////////////////////
CCryMemoryManager* CCryMemoryManager::GetInstance()
{
#ifdef MEMMAN_STATIC
	return &g_memoryManager;
#else
	static CCryMemoryManager memman;
	return &memman;
#endif
}

//////////////////////////////////////////////////////////////////////////
bool CCryMemoryManager::GetProcessMemInfo( SProcessMemInfo &minfo )
{
	ZeroStruct(minfo);

#if defined(WIN32) && !defined(XENON)

	MEMORYSTATUSEX mem;
	mem.dwLength = sizeof(mem);
	GlobalMemoryStatusEx ( &mem );

	minfo.TotalPhysicalMemory = mem.ullTotalPhys;
	minfo.FreePhysicalMemory = mem.ullAvailPhys;

	//////////////////////////////////////////////////////////////////////////
	typedef BOOL (WINAPI *GetProcessMemoryInfoProc)( HANDLE,PPROCESS_MEMORY_COUNTERS,DWORD );

	PROCESS_MEMORY_COUNTERS pc;
	ZeroStruct(pc);
	pc.cb = sizeof(pc);
	static HMODULE hPSAPI = LoadLibrary("psapi.dll");
	if (hPSAPI)
	{
		static GetProcessMemoryInfoProc pGetProcessMemoryInfo = (GetProcessMemoryInfoProc)GetProcAddress(hPSAPI, "GetProcessMemoryInfo");
		if (pGetProcessMemoryInfo)
		{
			if (pGetProcessMemoryInfo( GetCurrentProcess(), &pc, sizeof(pc) ))
			{
				minfo.PageFaultCount = pc.PageFaultCount;
				minfo.PeakWorkingSetSize = pc.PeakWorkingSetSize;
				minfo.WorkingSetSize = pc.WorkingSetSize;
				minfo.QuotaPeakPagedPoolUsage = pc.QuotaPeakPagedPoolUsage;
				minfo.QuotaPagedPoolUsage = pc.QuotaPagedPoolUsage;
				minfo.QuotaPeakNonPagedPoolUsage = pc.QuotaPeakNonPagedPoolUsage;
				minfo.QuotaNonPagedPoolUsage = pc.QuotaNonPagedPoolUsage;
				minfo.PagefileUsage = pc.PagefileUsage;
				minfo.PeakPagefileUsage = pc.PeakPagefileUsage;
			
				return true;
			}
		}
	}



































#endif
	return false;
}

//////////////////////////////////////////////////////////////////////////
void CCryMemoryManager::FakeAllocation( long size )
{
	CryInterlockedExchangeAdd(&g_TotalAllocatedMemory, size);
}

//////////////////////////////////////////////////////////////////////////
CCryMemoryManager::HeapHandle CCryMemoryManager::TraceDefineHeap( const char *heapName,size_t size,const void* pBase )
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////
void CCryMemoryManager::TraceHeapAlloc( HeapHandle heap,void* mem, size_t size, size_t blockSize,const char *sUsage,const char *sNameHint )
{

}

//////////////////////////////////////////////////////////////////////////
void CCryMemoryManager::TraceHeapFree( HeapHandle heap,void* mem, size_t blockSize )
{

}


//////////////////////////////////////////////////////////////////////////
void CCryMemoryManager::TraceHeapSetColor( uint32 color )
{

}

//////////////////////////////////////////////////////////////////////////
void CCryMemoryManager::TraceHeapSetLabel( const char *sLabel )
{

}

//////////////////////////////////////////////////////////////////////////
uint32 CCryMemoryManager::TraceHeapGetColor()
{
	return 0;
}

//////////////////////////////////////////////////////////////////////////
IMemReplay* CCryMemoryManager::GetIMemReplay()
{
#if CAPTURE_REPLAY_LOG
	return CMemReplay::GetInstance();
#else
	static IMemReplay m;
	return &m;
#endif
}

//////////////////////////////////////////////////////////////////////////
ICustomMemoryHeap* const CCryMemoryManager::CreateCustomMemoryHeapInstance(bool const bCanUseGPUMemory)
{
	return new CCustomMemoryHeap(bCanUseGPUMemory);
}

IGeneralMemoryHeap* CCryMemoryManager::CreateGeneralExpandingMemoryHeap(size_t upperLimit, size_t reserveSize, const char* sUsage)
{
	return new CGeneralMemoryHeap(static_cast<UINT_PTR>(0), upperLimit, reserveSize, sUsage);
}

IGeneralMemoryHeap* CCryMemoryManager::CreateGeneralMemoryHeap(void* base, size_t sz,const char *sUsage)
{
	return new CGeneralMemoryHeap(base, sz,sUsage);
}

IPageMappingHeap* CCryMemoryManager::CreatePageMappingHeap(size_t addressSpace, const char* sName)
{
	return new CPageMappingHeap(addressSpace, sName);
}



//////////////////////////////////////////////////////////////////////////
extern "C"
{
	CRYMEMORYMANAGER_API void CryGetIMemoryManagerInterface( void **pIMemoryManager )
	{
		// Static instance of the memory manager
		*pIMemoryManager = CCryMemoryManager::GetInstance();
	}
};